﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
using System.Threading;
using System.Windows;

namespace CardMonitor.Utils
{
    public class PortControlHelper
    {
        #region 字段/属性/委托
        /// <summary>  
        /// 串行端口对象  
        /// </summary>  
        private SerialPort sp;

        /// <summary>  
        /// 串口接收数据委托  
        /// </summary>  
        public delegate void ComReceiveDataHandler(string data);

        public ComReceiveDataHandler OnComReceiveDataHandler = null;

        /// <summary>  
        /// 端口名称数组  
        /// </summary>  
        public string[] PortNameArr { get; set; }

        /// <summary>  
        /// 串口通信开启状态  
        /// </summary>  
        public bool PortState { get; set; }

        /// <summary>  
        /// 编码类型  
        /// </summary>  
        public Encoding EncodingType { get; set; }
        #endregion

        private List<byte> buffer = new List<byte>(4096);

        #region 方法
        public PortControlHelper()
        {
            PortState = false;
            EncodingType = Encoding.ASCII;
            PortNameArr = SerialPort.GetPortNames();
            sp = new SerialPort();
            sp.DataReceived += new SerialDataReceivedEventHandler(DataReceived);
        }

        /// <summary>  
        /// 打开端口  
        /// </summary>  
        /// <param name="portName">端口名称</param>  
        /// <param name="boudRate">波特率</param>  
        /// <param name="dataBit">数据位</param>  
        /// <param name="stopBit">停止位</param>  
        /// <param name="timeout">超时时间</param>  
        public void OpenPort(string portName, int boudRate = 115200, int dataBit = 8, int stopBit = 1, int timeout = 5000)
        {
            try
            {
                sp.PortName = portName;
                sp.BaudRate = boudRate;
                sp.DataBits = dataBit;
                sp.StopBits = (StopBits)stopBit;
                sp.ReadTimeout = timeout;
                sp.Open();
                PortState = true;
            }
            catch (Exception e)
            {
                //throw e;
            }
        }

        /// <summary>  
        /// 关闭端口  
        /// </summary>  
        public void ClosePort()
        {
            try
            {
                sp.Close();
                PortState = false;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        /// <summary>  
        /// 发送数据  
        /// </summary>  
        /// <param name="sendData"></param>  
        public void SendData(string sendData)
        {
            try
            {
                sp.Encoding = EncodingType;
                sp.Write(sendData);
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public void SendHexData(string sendData)//端口关闭
        {
            try
            {
                byte[] bytes = ByteUtils.strToToHexByte(sendData);
                sp.IsOpen.ToString();
                //sp.Encoding = EncodingType;
                //  MessageBox.Show();
                sp.Write(bytes, 0, bytes.Length);
               
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                throw e;
            }
        }

        public void SendByteData(byte[] sendData)
        {
            try
            {
                sp.Encoding = EncodingType;
                sp.Write(sendData, 0, sendData.Length);
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        /// <summary>  
        /// 接收数据回调用  
        /// </summary>  
        /// <param name="sender"></param>  
        /// <param name="e"></param>  
        private void DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int n = sp.BytesToRead;
            byte[] buf = new byte[n];
            sp.Read(buf, 0, n);

            //1.缓存数据
            this.buffer.AddRange(buf);
            //2.完整性判断
            while (this.buffer.Count >= 5) //至少包含帧头（2字节）、长度（1字节）、校验位（1字节）；
            {
                Console.WriteLine(ByteUtils.byteToHexStr(buf));
                //2.1 查找数据头
                if (this.buffer[0] == 0xFF && this.buffer[1] == 0xCC) //传输数据有帧头，用于判断
                {
                    if (this.buffer[3] == 0x68)
                    {
                        if (this.buffer.Count < 37) break;
                        byte[] ReceiveBytes = new byte[37];
                        this.buffer.CopyTo(ReceiveBytes, 0);
                        this.buffer.RemoveRange(0, 37);

                        String hexString = ByteUtils.byteToHexStr(ReceiveBytes);
                        if (OnComReceiveDataHandler != null)
                        {
                            OnComReceiveDataHandler(hexString);
                        }
                    }
                    else if (this.buffer[3] == 0x69)
                    {
                        if (this.buffer.Count < 21) break;
                        byte[] ReceiveBytes = new byte[21];
                        this.buffer.CopyTo(ReceiveBytes, 0);
                        this.buffer.RemoveRange(0, 21);

                        String hexString = ByteUtils.byteToHexStr(ReceiveBytes);
                        if (OnComReceiveDataHandler != null)
                        {
                            OnComReceiveDataHandler(hexString);
                        }
                    }
                    else if (this.buffer[3] == 0x67)
                    {
                        if (this.buffer.Count < 13) break;
                        byte[] ReceiveBytes = new byte[13];
                        this.buffer.CopyTo(ReceiveBytes, 0);
                        this.buffer.RemoveRange(0, 13);

                        String hexString = ByteUtils.byteToHexStr(ReceiveBytes);
                        if (OnComReceiveDataHandler != null)
                        {
                            OnComReceiveDataHandler(hexString);
                        }
                    }
                    else if (this.buffer[3] == 0x62)
                    {
                        if (this.buffer.Count < 9) break;
                        byte[] ReceiveBytes = new byte[9];
                        this.buffer.CopyTo(ReceiveBytes, 0);
                        this.buffer.RemoveRange(0, 9);

                        String hexString = ByteUtils.byteToHexStr(ReceiveBytes);
                        if (OnComReceiveDataHandler != null)
                        {
                            OnComReceiveDataHandler(hexString);
                        }
                    }
                    else
                    {
                        Console.WriteLine("********");
                        this.buffer.RemoveRange(0, this.buffer.Count);
                    }
                }
                else
                {
                    this.buffer.RemoveRange(0, this.buffer.Count);
                }
            }
            /*
            byte[] buffer = new byte[sp.BytesToRead];
            sp.Read(buffer, 0, buffer.Length);

            String hexString = ByteUtils.byteToHexStr(buffer);

            string str = hexString;

            if (OnComReceiveDataHandler != null)
            {
                OnComReceiveDataHandler(str);
            }*/
        }
        #endregion

        public static int openDoor(String com, int id)
        {
            int result = 0;
            try
            {
                PortControlHelper pchSend = new PortControlHelper(); ;
                //pchSend.OpenPort("COM2", 9600, 8, 1);
                pchSend.OpenPort(com, 9600, 8, 1);

                byte[] byte01 = new byte[10];
                byte01[0] = 0x48;
                byte01[1] = 0x3A;
                byte01[2] = 0x01;
                byte01[3] = 0x70;
                //byte01[4] = 0x01;
                if (id == 1)
                {
                    byte01[4] = 0x01;
                }
                else if (id == 2)
                {
                    byte01[4] = 0x02;
                }
                else if (id == 3)
                {
                    byte01[4] = 0x03;
                }
                else if (id == 4)
                {
                    byte01[4] = 0x04;
                }
                byte01[5] = 0x01;
                byte01[6] = 0x00;
                byte01[7] = 0x00;
                byte01[8] = 0x45;
                byte01[9] = 0x44;

                pchSend.SendByteData(byte01);

                Thread.Sleep(1000);

                byte01[5] = 0x00;
                pchSend.SendByteData(byte01);

                pchSend.ClosePort();
                result = 1;
            }
            catch (Exception ex)
            {
                result = 0;
            }
            return result;
        }
        #region 写IC卡功能

        /// <summary>
        /// 写IC卡数据
        /// </summary>
        /// <param name="com">串口号</param>
        /// <param name="cardAddress">卡机地址</param>
        /// <param name="data">要写入的数据</param>
        /// <returns>操作结果</returns>
        public bool WriteICCardData(string com, byte cardAddress, byte[] data)
        {
            bool result = false;
            try
            {
                PortControlHelper pchSend = new PortControlHelper();
               // pchSend.OpenPort(com, 9600, 8, 1);

                // 构建写IC卡命令包
                List<byte> commandPacket = new List<byte>();
                commandPacket.Add(0xF2); // STX
                commandPacket.Add(cardAddress); // ADDR
                commandPacket.Add((byte)((data.Length + 11) >> 8)); // LENH
                commandPacket.Add((byte)(data.Length + 11)); // LENL
                commandPacket.Add(0x43); // CMT 'C'
                commandPacket.Add(0x51); // CM 51H 写IC卡命令
                commandPacket.Add(0x30); // PM 写IC卡命令参数
                commandPacket.AddRange(data); // DATA
                commandPacket.Add(0x03); // ETX

                // 计算BCC
                byte bcc = 0;
                foreach (byte b in commandPacket)
                {
                    bcc ^= b;
                }
                commandPacket.Add(bcc); // BCC

                // 发送命令包
                pchSend.SendByteData(commandPacket.ToArray());

                // 等待响应
                Thread.Sleep(1000);

                // 检查响应
                // 注意：这里需要实现接收响应并检查是否成功
                // 示例代码中省略了这部分，实际应用中需根据实际情况实现
                // 假设成功
                result = true;

                pchSend.ClosePort();
            }
            catch (Exception ex)
            {
                result = false;
            }
            return result;
        }

        #endregion
        #region 写IC卡功能

        /// <summary>
        /// 写IC卡数据（支持字符串参数）
        /// </summary>
        /// <param name="com">串口号</param>
        /// <param name="cardAddress">卡机地址0x01,</param>
        /// <param name="hexData">十六进制字符串数据（例："A1B2C3D4"）</param>
        /// <returns>操作结果</returns>
        public bool WriteICCardData(string com, byte cardAddress, string hexData)
        {
            bool result = false;
            try
            {
                // 参数验证
                if (string.IsNullOrWhiteSpace(hexData) || hexData.Length % 2 != 0)
                {
                    throw new ArgumentException("无效的十六进制数据，长度必须为偶数");
                }

                // 使用现有工具类转换（与SendHexData逻辑一致）
                byte[] dataBytes = ByteUtils.strToToHexByte(hexData);

                PortControlHelper pchSend = new PortControlHelper();
                pchSend.OpenPort(com, 9600, 8, 1);

                // 构建写IC卡命令包（保持原有协议结构）
                List<byte> commandPacket = new List<byte>();
                commandPacket.Add(0xF2);                 // STX
                commandPacket.Add(cardAddress);          // ADDR
                commandPacket.Add((byte)((dataBytes.Length + 11) >> 8)); // LENH
                commandPacket.Add((byte)(dataBytes.Length + 11));        // LENL
                commandPacket.Add(0x43);                 // CMT 'C'
                commandPacket.Add(0x51);                 // CM 51H 写IC卡命令
                commandPacket.Add(0x30);                 // PM 写IC卡命令参数
                commandPacket.AddRange(dataBytes);        // DATA
                commandPacket.Add(0x03);                 // ETX

                // BCC校验计算（与现有协议一致）
                byte bcc = 0;
                foreach (byte b in commandPacket)
                {
                    bcc ^= b;
                }
                commandPacket.Add(bcc);

                // 重用现有发送方法
                pchSend.SendByteData(commandPacket.ToArray());

                // 保持原有等待逻辑
                Thread.Sleep(1000);

                // 这里应添加实际响应验证（根据设备协议）
                // 示例保持原有假设成功逻辑
                result = true;

                pchSend.ClosePort();
            }
            catch (ArgumentException ex)
            {
                Console.WriteLine($"参数错误: {ex.Message}");
                result = false;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"操作失败: {ex.Message}");
                result = false;
            }
            return result;
        }

        #endregion

    }
}
